from flask import Flask, render_template, request, redirect, url_for, session
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Pie, Bar, Scatter, Page, Tab
from pyecharts.components import Table
from pyecharts.globals import ThemeType
import os

app = Flask(__name__)
app.secret_key = 'your_secret_key_here'  # 用于会话加密，实际部署时应使用强密钥

# 模拟用户数据库
USERS = {
    'admin': 'admin123',
    'user1': 'password1'
}


@app.route('/')
def home():
    if 'username' in session:
        return redirect(url_for('dashboard'))
    return redirect(url_for('login'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        if username in USERS and USERS[username] == password:
            session['username'] = username
            return redirect(url_for('dashboard'))
        else:
            return render_template('login.html', error='无效的用户名或密码')

    return render_template('login.html')


@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('login'))


@app.route('/dashboard')
def dashboard():
    if 'username' not in session:
        return redirect(url_for('login'))

    # 创建可视化图表
    df = pd.read_csv('D:\keshe2\loan_applications.csv')

    # 创建Tab对象
    tab = Tab()

    # 1. 不同贷款类型数量占比饼图
    loan_type_counts = df['loan_type'].value_counts().reset_index(name='数量')
    pie = (
        Pie(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add(
            "贷款类型",
            [list(z) for z in zip(loan_type_counts['loan_type'], loan_type_counts['数量'])],
            radius=["40%", "75%"],
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="不同贷款类型数量占比"),
            legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%"),
            toolbox_opts=opts.ToolboxOpts(is_show=True)
        )
        .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))
    )
    tab.add(pie, "贷款类型占比")

    # 2. 申请贷款金额的直方图
    hist, bins = pd.cut(df['loan_amount_requested'], bins=20, retbins=True)
    hist_counts = hist.value_counts()
    bar_hist = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis([str(interval) for interval in hist_counts.index])
        .add_yaxis("数量", hist_counts.tolist())
        .set_global_opts(
            title_opts=opts.TitleOpts(title="申请贷款金额分布直方图"),
            xaxis_opts=opts.AxisOpts(name="申请贷款金额区间", axislabel_opts={"rotate": 45}),
            yaxis_opts=opts.AxisOpts(name="数量"),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            datazoom_opts=[opts.DataZoomOpts()]
        )
    )
    tab.add(bar_hist, "贷款金额分布")

    # 3. 就业状态与贷款状态的关系堆叠柱状图
    employment_loan_status = pd.crosstab(df['employment_status'], df['loan_status'])
    bar_stacked = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(employment_loan_status.index.tolist())
    )
    for status in employment_loan_status.columns:
        bar_stacked.add_yaxis(status, employment_loan_status[status].tolist(), stack="stack1")
    bar_stacked.set_global_opts(
        title_opts=opts.TitleOpts(title="就业状态与贷款状态的关系"),
        xaxis_opts=opts.AxisOpts(name="就业状态"),
        yaxis_opts=opts.AxisOpts(name="数量"),
        legend_opts=opts.LegendOpts(pos_top="5%"),
        toolbox_opts=opts.ToolboxOpts(is_show=True)
    ).set_series_opts(label_opts=opts.LabelOpts(position="inside"))
    tab.add(bar_stacked, "就业与贷款状态")

    # 4. 申请贷款金额和提供的利率的散点图
    scatter = (
        Scatter(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(df['loan_amount_requested'].tolist())
        .add_yaxis(
            "利率",
            df['interest_rate_offered'].tolist(),
            symbol_size=10,
            label_opts=opts.LabelOpts(is_show=False),
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="申请贷款金额和提供的利率的关系"),
            xaxis_opts=opts.AxisOpts(name="申请贷款金额"),
            yaxis_opts=opts.AxisOpts(name="提供的利率"),
            toolbox_opts=opts.ToolboxOpts(is_show=True)
        )
    )
    tab.add(scatter, "金额与利率关系")

    # 5. 不同目的贷款数量柱状图
    purpose_counts = df['purpose_of_loan'].value_counts().reset_index(name='数量')
    bar_purpose = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(purpose_counts['purpose_of_loan'].tolist())
        .add_yaxis("数量", purpose_counts['数量'].tolist())
        .set_global_opts(
            title_opts=opts.TitleOpts(title="不同目的贷款数量柱状图"),
            xaxis_opts=opts.AxisOpts(name="贷款目的", axislabel_opts={"rotate": 90}),
            yaxis_opts=opts.AxisOpts(name="数量"),
            toolbox_opts=opts.ToolboxOpts(is_show=True),
            datazoom_opts=[opts.DataZoomOpts()]
        )
    )
    tab.add(bar_purpose, "贷款目的")

    # 6. 不同性别贷款申请数量柱状图
    gender_counts = df['gender'].value_counts().reset_index(name='数量')
    bar_gender = (
        Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
        .add_xaxis(gender_counts['gender'].tolist())
        .add_yaxis("数量", gender_counts['数量'].tolist())
        .set_global_opts(
            title_opts=opts.TitleOpts(title="不同性别贷款申请数量柱状图"),
            xaxis_opts=opts.AxisOpts(name="性别"),
            yaxis_opts=opts.AxisOpts(name="数量"),
            toolbox_opts=opts.ToolboxOpts(is_show=True)
        )
    )
    tab.add(bar_gender, "性别分布")

    # 7. 添加数据概览表格
    table = Table()
    headers = ["字段名", "数据类型", "描述"]
    rows = [
        ["loan_type", "字符串", "贷款类型"],
        ["loan_amount_requested", "数值", "申请贷款金额"],
        ["employment_status", "字符串", "就业状态"],
        ["loan_status", "字符串", "贷款状态"],
        ["interest_rate_offered", "数值", "提供的利率"],
        ["purpose_of_loan", "字符串", "贷款目的"],
        ["gender", "字符串", "性别"]
    ]
    table.add(headers, rows).set_global_opts(
        title_opts=opts.ComponentTitleOpts(title="数据字段概览")
    )
    tab.add(table, "数据概览")

    # 渲染为HTML文件
    output_path = os.path.join('tem', 'dashboard.html')
    tab.render(output_path)

    return render_template('dashboard.html', username=session['username'])


if __name__ == '__main__':
    # 确保templates目录存在
    if not os.path.exists('tem'):
        os.makedirs('tem')

    app.run(debug=True)